/*! \file 
    \brief Holds the implementation of the synchronization sub-system. */

#include "kernel.h"
#include "sync.h"


void
initialize_thread_synchronization(void)
{
	int i;
	for(i = 0; i < sizeof (semaphore_table) / sizeof (semaphore_table[0]); i++){
		semaphore_table[i].count = 0;
		semaphore_table[i].owner = -1;
		semaphore_table[i].blocked.head = 0;
		semaphore_table[i].blocked.tail = 0;
	}
}

void
semaphore_reset(long semaphore_handle){
	semaphore_table[semaphore_handle].owner = -1;
	semaphore_table[semaphore_handle].count = 0;
	semaphore_table[semaphore_handle].blocked.head = 0;
	semaphore_table[semaphore_handle].blocked.tail = 0;
	return;
}


int
semaphore_enqueue(int thread_index, long semaphore_handle)
{
	const int tail = semaphore_table[semaphore_handle].blocked.tail;
	const int head = semaphore_table[semaphore_handle].blocked.head;
	int faliure = 0;
	
	if (tail == MAX_NUMBER_OF_BLOCKED_SEMAPHORE_THREADS-1) {
		if (head == 0) {
			// The semaphore queue is full, return error.
			faliure = 1;
		} else {
			semaphore_table[semaphore_handle].blocked.tail = 0;
		}
	} else {
		if ( tail+1 == head ) {
			// The semaphore queue is full, return error.
			faliure = 2;
		} else {
			semaphore_table[semaphore_handle].blocked.tail++;
		}
	}
	
	if (faliure != 0){
		return faliure;
	}
	
	semaphore_table[semaphore_handle].blocked.blocked_threads[tail] = thread_index;
	return 0;
	
}

int
semaphore_dequeue(long semaphore_handle){
	const int tail = semaphore_table[semaphore_handle].blocked.tail;
	const int head = semaphore_table[semaphore_handle].blocked.head;
	int thread_index;
	
	if (head == tail) {
		return -1;
	} else {
		if (head == MAX_NUMBER_OF_BLOCKED_SEMAPHORE_THREADS-1) {
			semaphore_table[semaphore_handle].blocked.head = 0;
		} else {
			semaphore_table[semaphore_handle].blocked.head++;
		}
		thread_index = semaphore_table[semaphore_handle].blocked.blocked_threads[head];
		return thread_index;
	}
	
	
	
}
/* Put any code you need to add to implement assignment 5 here. */
